package p0test;

import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.NumericField;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;

import java.io.File;
import java.io.IOException;
import java.util.Date;

import static org.apache.lucene.document.Field.Index.ANALYZED;

public class IndexUtils {
    private String[] ids = {"123", "1234", "12345", "4", "5", "6"};

    private String[] emails = {
            "zhangsan@sina.com",
            "lisi@sina.com",
            "wangwu@sina.com",
            "zhaoliu@sina.com",
            "qianqi@sina.com",
            "sunba@sina.com"};

    private String[] contents = {
            "this is zhangsan lisi",
            "this is lisi home",
            "this is wangwu home",
            "this is zhaoliu home",
            "this is qianqi home",
            "this is sunba.com home"};
    private Date[] dates={new Date(),new Date(),new Date(),new Date(),new Date(),new Date()};
    private String[] names = {"zhansan", "lisi", "wangwu", "zhaoliu", "qianqi", "sunba"};

    private int[] ataches = {2, 3, 1, 4, 5, 5};

    /**
     * 一般reader 一个项目只有一个，有些项目的writer也只有一个，也就是
     * 写完后不close(),不close的话怎么提交索引呢，，用 writer.commit();
     */
    public void index() {

        IndexWriter indexWriter = null;
        try {
            Directory directory = FSDirectory.open(new File("D:/lucene/index02"));
            IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35));
            System.out.println("=====" + directory);
            indexWriter=new IndexWriter(directory,iwc);
            indexWriter.deleteAll();
            Document document = null;
            for (int i = 0; i < ids.length; i++) {
                //第三个参数表示 是否存入索引中，
                document = new Document();
                document.add(new Field("id", ids[i], Field.Store.YES, Field.Index.ANALYZED));
                document.add(new Field("email", emails[i], Field.Store.YES, Field.Index.ANALYZED));
                document.add(new Field("content", contents[i], Field.Store.NO, Field.Index.ANALYZED));
                document.add(new Field("name", names[i], Field.Store.YES, Field.Index.ANALYZED_NO_NORMS));
                //加权操作比如对shangsan 加权,默认是1.0
                if(emails[i].equals("zhangsan@sina.com") || emails[i].equals("sunba@sina.com")){
                    document.setBoost(2.0f);
                }
                //对数字和日期进行索引，日期其实就是数字，所以都用numberField
                document.add(new NumericField("date",Field.Store.YES,true).setLongValue(dates[i].getTime()));
                indexWriter.addDocument(document);


            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (indexWriter != null) {
                try {
                    indexWriter.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
    }

    public void query() {
        try {
            Directory directory = FSDirectory.open(new File("d://lucene/index02"));
            //一般创建indexreader的时候用单列的，但是有一个问题就是 对于新增或删除或修改的
            //索引 indexReader感知不到，为了解决这种情况，提供了 IndexReader.openIfChanged(olderReader)
            //（上面的方法创建单列的时候使用）
            //意思就是如果索引变化了的话 就会重新创建reader
            IndexReader indexReader = IndexReader.open(directory);
            //存储的文档数,通过reader可以获取文档的数量
            System.out.println("存储的文档数" + indexReader.numDocs());
            System.out.println("文档的总数" + indexReader.maxDoc());
            IndexSearcher indexSearcher = new IndexSearcher(indexReader);
            //QueryParser queryParser = new QueryParser(Version.LUCENE_35, "email", new StandardAnalyzer(Version.LUCENE_35));
            //Query query = queryParser.parse("@");
            //如果是精确搜索，没有分词的话可以直接用 TermQuery
            TermQuery query=new TermQuery(new Term("name","zhangsan lisi"));
            TopDocs td = indexSearcher.search(query, 10);
            ScoreDoc[] sds = td.scoreDocs;
            for (ScoreDoc sd : sds) {
                Document doc = indexSearcher.doc(sd.doc);
                System.out.println(doc.get("id"));
                System.out.println(doc.get("email"));
                //index时的那个document
                //这个bost值永远都是默认1.0 应为这个doc是这里新建的，，不是创建
                System.out.println(doc.getBoost());
                //这个score是根据 boost的值算出来的，具体怎么算？
                System.out.println(sd.score);

            }
        } catch (Exception e) {
            e.printStackTrace();

        }
    }

    public void delete() {
        IndexWriter indexWriter = null;
        try {
            Directory directory = FSDirectory.open(new File("d://lucene/index02"));
            IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35));
            indexWriter = new IndexWriter(directory, config);
            //参数可以是一个query 也可以是一个term 下面表示删除id为1的
            //此时的删除并不是测底的删除而是放到一个回收站一样的文件中可以恢复
            //还可以用reader来删除文档
            indexWriter.deleteDocuments(new Term("id", "1"));
            indexWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 删除所有索引
     */
    public void deleteAll() {
        IndexWriter indexWriter = null;
        try {
            Directory directory = FSDirectory.open(new File("d://lucene/index02"));
            IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35));
            indexWriter = new IndexWriter(directory, config);
            indexWriter.deleteAll();
            indexWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void queryDeleteDocs() {
        try {
            Directory directory = FSDirectory.open(new File("d://lucene/index02"));
            IndexReader ir = IndexReader.open(directory);
            System.out.println("numDocs:" + ir.numDocs());
            System.out.println("maxDocs:" + ir.maxDoc());
            System.out.println("deleteDocs:" + ir.numDeletedDocs());
            ir.close();
        } catch (Exception e) {

        } finally {

        }
    }

    /**
     * 恢复删除的索引文档
     */
    public void unDelete() {
        try {
            Directory directory = FSDirectory.open(new File("d://lucene/index02"));
            //第二个参数表示 readonly的值，恢复是必须把这个参数设置为false
            IndexReader ir = IndexReader.open(directory, false);
            ir.undeleteAll();
            ir.close();
        } catch (Exception e) {

        } finally {

        }
    }

    /**
     * 强制删除，相当于清空回收站
     */
    public void forceDelete() {
        try {
            Directory directory = FSDirectory.open(new File("d://lucene/index02"));
            IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35));
            IndexWriter iw = new IndexWriter(directory, config);
            iw.forceMergeDeletes();
            iw.close();
        } catch (Exception e) {

        } finally {

        }
    }

    /**
     * 合并索引文件，一般不建议做，会消耗大量开销，lucene会自动做
     */
    public void mergeIndex() {
        try {
            Directory directory = FSDirectory.open(new File("d://lucene/index02"));
            //第二个参数表示 readonly的值，恢复是必须把这个参数设置为false
            IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35));
            IndexWriter iw = new IndexWriter(directory, config);
            //2 表示合并成几段，可以查看文件 保留了一段没有删除，剩下的合并成一段，注意：
            //如果有被删除的文档的话会被清空（清空回收站）
            iw.forceMerge(2);
            iw.close();
        } catch (Exception e) {

        } finally {

        }
    }

    /**
     * 更新索引文件，所谓的update其实是 delete 再save操作
     */
    public void update() {
        try {
            Directory directory = FSDirectory.open(new File("d://lucene/index02"));
            //第二个参数表示 readonly的值，恢复是必须把这个参数设置为false
            IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35));
            IndexWriter idw = new IndexWriter(directory, config);
            //lucene其实并没有提供update操作，所谓的update其实是 delete 再save操作。
            Document document=new Document();
            document.add(new Field("id", ids[1], Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));
            document.add(new Field("email", emails[1], Field.Store.YES, Field.Index.ANALYZED_NO_NORMS));
            document.add(new Field("content", contents[1], Field.Store.NO, ANALYZED));
            document.add(new Field("name", names[1], Field.Store.YES, Field.Index.ANALYZED_NO_NORMS));
            //从下面面两个参数可以看出，先删除 id=1 的然后save 新的document
            idw.updateDocument(new Term("id","1"),document);
            idw.close();
        } catch (Exception e) {

        } finally {

        }
    }
}
